/*
 * Copyright (c) 2021-2023 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include "hdf_audio_server_render.h"
#include "audio_uhdf_log.h"
#include "hdf_audio_server_common.h"
#include "hdf_audio_server_manager.h"
#include "osal_mutex.h"

#define HDF_LOG_TAG HDF_AUDIO_HAL_STUB
#define IF_TRUE_PRINT_LOG_RETURN_ERROR(cond, log, err) \
    if (cond) { \
        AUDIO_FUNC_LOGE(log); \
        return err; \
    }
struct OsalMutex g_renderLock;

static int32_t GetInitRenderParaAttrs(struct HdfSBuf *data, struct AudioSampleAttributes *attrs)
{
    if (data == NULL || attrs == NULL) {
        return HDF_FAILURE;
    }
    uint32_t tempRenderPara = 0;
    if (!HdfSbufReadUint32(data, &tempRenderPara)) {
        AUDIO_FUNC_LOGE("read tempRenderPara fail");
        return HDF_FAILURE;
    }
    attrs->type = (enum AudioCategory)tempRenderPara;
    if (!HdfSbufReadUint32(data, &attrs->period)) {
        AUDIO_FUNC_LOGE("read period fail");
        return HDF_FAILURE;
    }
    if (!HdfSbufReadUint32(data, &attrs->frameSize)) {
        AUDIO_FUNC_LOGE("read frameSize fail");
        return HDF_FAILURE;
    }
    if (!HdfSbufReadUint32(data, &attrs->startThreshold)) {
        AUDIO_FUNC_LOGE("read startThreshold fail");
        return HDF_FAILURE;
    }
    if (!HdfSbufReadUint32(data, &attrs->stopThreshold)) {
        AUDIO_FUNC_LOGE("read stopThreshold fail");
        return HDF_FAILURE;
    }
    if (!HdfSbufReadUint32(data, &attrs->silenceThreshold)) {
        AUDIO_FUNC_LOGE("read silenceThreshold fail");
        return HDF_FAILURE;
    }
    if (!HdfSbufReadUint32(data, &tempRenderPara)) {
        AUDIO_FUNC_LOGE("read bool isBigEndian fail");
        return HDF_FAILURE;
    }
    attrs->isBigEndian = (bool)tempRenderPara;

    if (!HdfSbufReadUint32(data, &tempRenderPara)) {
        AUDIO_FUNC_LOGE("read attrs isSignedData fail");
        return HDF_FAILURE;
    }
    attrs->isSignedData = (bool)tempRenderPara;

    if (!HdfSbufReadInt32(data, &attrs->streamId)) {
        AUDIO_FUNC_LOGE("read streamId fail");
        return HDF_FAILURE;
    }

    return HDF_SUCCESS;
}

static int32_t GetInitRenderPara(struct HdfSBuf *data, struct AudioDeviceDescriptor *devDesc,
    struct AudioSampleAttributes *attrs)
{
    if (data == NULL || devDesc == NULL || attrs == NULL) {
        return HDF_FAILURE;
    }
    uint32_t tempRenderPara = 0;
    if (!HdfSbufReadUint32(data, &tempRenderPara)) {
        AUDIO_FUNC_LOGE("read attrs format fail");
        return HDF_FAILURE;
    }
    attrs->format = (enum AudioFormat)tempRenderPara;
    if (!HdfSbufReadUint32(data, &attrs->channelCount)) {
        AUDIO_FUNC_LOGE("read channelCount fail");
        return HDF_FAILURE;
    }
    if (!HdfSbufReadUint32(data, &attrs->sampleRate)) {
        AUDIO_FUNC_LOGE("read sampleRate fail");
        return HDF_FAILURE;
    }
    if (!HdfSbufReadUint32(data, &tempRenderPara)) {
        AUDIO_FUNC_LOGE("read attrs interleaved fail");
        return HDF_FAILURE;
    }
    attrs->interleaved = (bool)tempRenderPara;

    if (GetInitRenderParaAttrs(data, attrs) < 0) {
        return HDF_FAILURE;
    }

    if (!HdfSbufReadUint32(data, &devDesc->portId)) {
        AUDIO_FUNC_LOGE("read portId fail");
        return HDF_FAILURE;
    }
    if (!HdfSbufReadUint32(data, &tempRenderPara)) {
        AUDIO_FUNC_LOGE("read tempRenderPara fail");
        return HDF_FAILURE;
    }
    devDesc->pins = (enum AudioPortPin)tempRenderPara;
    devDesc->desc = NULL;
    return HDF_SUCCESS;
}

int32_t HdiServiceCreatRender(const struct HdfDeviceIoClient *client,
    struct HdfSBuf *data, struct HdfSBuf *reply)
{
    IF_TRUE_PRINT_LOG_RETURN_ERROR((client == NULL || data == NULL || reply == NULL),
        "client or data or reply is null!", AUDIO_HAL_ERR_INVALID_PARAM);
    struct AudioAdapter *adapter = NULL;
    struct AudioDeviceDescriptor devDesc;
    struct AudioSampleAttributes attrs;
    struct AudioRender *render = NULL;
    const char *adapterName = NULL;
    uint32_t renderPid = 0;
    IF_TRUE_PRINT_LOG_RETURN_ERROR(((adapterName = HdfSbufReadString(data)) == NULL),
        "adapterNameCase Is NULL", AUDIO_HAL_ERR_INVALID_PARAM);
    IF_TRUE_PRINT_LOG_RETURN_ERROR((!HdfSbufReadUint32(data, &renderPid)),
        "read renderPid fail", AUDIO_HAL_ERR_INTERNAL);
    int32_t ret = GetInitRenderPara(data, &devDesc, &attrs);
    IF_TRUE_PRINT_LOG_RETURN_ERROR((ret < 0), "GetInitRenderPara fail", AUDIO_HAL_ERR_INTERNAL);
    ret = AudioAdapterListGetAdapter(adapterName, &adapter);
    IF_TRUE_PRINT_LOG_RETURN_ERROR((ret < 0), "AudioAdapterListGetAdapter fail", AUDIO_HAL_ERR_INTERNAL);
    IF_TRUE_PRINT_LOG_RETURN_ERROR((adapter == NULL), "adapter is NULL!", AUDIO_HAL_ERR_INVALID_PARAM);
    const int32_t priority = attrs.type;
    ret = AudioCreatRenderCheck(adapterName, priority);
    IF_TRUE_PRINT_LOG_RETURN_ERROR((ret < 0), "AudioCreatRenderCheck: Render is working can not replace!", ret);
    IF_TRUE_PRINT_LOG_RETURN_ERROR((adapter->CreateRender == NULL), "CreateRender is NULL", AUDIO_HAL_ERR_INTERNAL);
    ret = adapter->CreateRender(adapter, &devDesc, &attrs, &render);
    IF_TRUE_PRINT_LOG_RETURN_ERROR((render == NULL || ret < 0), "Failed to CreateRender", AUDIO_HAL_ERR_INTERNAL);
    if (AudioAddRenderInfoInAdapter(adapterName, render, adapter, priority, renderPid)) {
        AUDIO_FUNC_LOGE("AudioAddRenderInfoInAdapter");
        adapter->DestroyRender(adapter, render);
        return AUDIO_HAL_ERR_INTERNAL;
    }
    OsalMutexInit(&g_renderLock);
    return AUDIO_HAL_SUCCESS;
}

int32_t HdiServiceRenderDestory(const struct HdfDeviceIoClient *client,
    struct HdfSBuf *data, struct HdfSBuf *reply)
{
    if (client == NULL || data == NULL || reply == NULL) {
        return AUDIO_HAL_ERR_INVALID_PARAM;
    }
    struct AudioAdapter *adapter = NULL;
    struct AudioRender *render = NULL;
    const char *adapterName = NULL;
    uint32_t pid = 0;

    OsalMutexDestroy(&g_renderLock);
    if (HdiServiceRenderCaptureReadData(data, &adapterName, &pid) < 0) {
        return AUDIO_HAL_ERR_INTERNAL;
    }
    int32_t ret = AudioAdapterListGetRender(adapterName, &render, pid);
    if (ret < 0) {
        return ret;
    }
    ret = AudioAdapterListGetAdapterRender(adapterName, &adapter, &render);
    if (ret < 0) {
        return ret;
    }
    if (adapter == NULL || render == NULL) {
        return AUDIO_HAL_ERR_INVALID_PARAM;
    }
    if (adapter->DestroyRender == NULL) {
        AUDIO_FUNC_LOGE("DestroyRender is NULL");
        return AUDIO_HAL_ERR_INTERNAL;
    }
    ret = adapter->DestroyRender(adapter, render);
    if (ret < 0) {
        AUDIO_FUNC_LOGE("DestroyRender failed!");
        return ret;
    }
    if (AudioDestroyRenderInfoInAdapter(adapterName) < 0) {
        return AUDIO_HAL_ERR_INTERNAL;
    }
    return AUDIO_HAL_SUCCESS;
}

int32_t HdiServiceRenderStart(const struct HdfDeviceIoClient *client, struct HdfSBuf *data, struct HdfSBuf *reply)
{
    if (client == NULL || data == NULL || reply == NULL) {
        return AUDIO_HAL_ERR_INVALID_PARAM;
    }
    struct AudioRender *render = NULL;
    int ret = AudioAdapterListCheckAndGetRender(&render, data);
    if (ret < 0) {
        return ret;
    }
    if (render == NULL || render->control.Start == NULL) {
        AUDIO_FUNC_LOGE("render or Start is NULL");
        return AUDIO_HAL_ERR_INTERNAL;
    }
    return render->control.Start((AudioHandle)render);
}

int32_t HdiServiceRenderStop(const struct HdfDeviceIoClient *client, struct HdfSBuf *data, struct HdfSBuf *reply)
{
    if (client == NULL || data == NULL || reply == NULL) {
        return AUDIO_HAL_ERR_INVALID_PARAM;
    }
    struct AudioRender *render = NULL;
    int ret = AudioAdapterListCheckAndGetRender(&render, data);
    if (ret < 0) {
        return ret;
    }
    if (render == NULL || render->control.Stop == NULL) {
        AUDIO_FUNC_LOGE("render or Stop is NULL");
        return AUDIO_HAL_ERR_INTERNAL;
    }
    return render->control.Stop((AudioHandle)render);
}

int32_t HdiServiceRenderPause(const struct HdfDeviceIoClient *client,
    struct HdfSBuf *data, struct HdfSBuf *reply)
{
    if (client == NULL || data == NULL || reply == NULL) {
        return AUDIO_HAL_ERR_INVALID_PARAM;
    }
    struct AudioRender *render = NULL;
    int ret = AudioAdapterListCheckAndGetRender(&render, data);
    if (ret < 0) {
        return ret;
    }
    if (render == NULL || render->control.Pause == NULL) {
        AUDIO_FUNC_LOGE("render or Pause is NULL");
        return AUDIO_HAL_ERR_INTERNAL;
    }
    return render->control.Pause((AudioHandle)render);
}

int32_t HdiServiceRenderResume(const struct HdfDeviceIoClient *client, struct HdfSBuf *data, struct HdfSBuf *reply)
{
    if (client == NULL || data == NULL || reply == NULL) {
        return AUDIO_HAL_ERR_INVALID_PARAM;
    }
    struct AudioRender *render = NULL;
    int ret = AudioAdapterListCheckAndGetRender(&render, data);
    if (ret < 0) {
        return ret;
    }
    if (render == NULL || render->control.Resume == NULL) {
        AUDIO_FUNC_LOGE("render or Resume is NULL");
        return AUDIO_HAL_ERR_INTERNAL;
    }
    return render->control.Resume((AudioHandle)render);
}

int32_t HdiServiceRenderFlush(const struct HdfDeviceIoClient *client, struct HdfSBuf *data, struct HdfSBuf *reply)
{
    if (client == NULL || data == NULL || reply == NULL) {
        AUDIO_FUNC_LOGE("The parameter is empty");
        return AUDIO_HAL_ERR_INVALID_PARAM;
    }
    struct AudioRender *render = NULL;
    int ret = AudioAdapterListCheckAndGetRender(&render, data);
    if (ret < 0) {
        return ret;
    }
    if (render == NULL || render->control.Flush == NULL) {
        AUDIO_FUNC_LOGE("render or Flush is NULL");
        return AUDIO_HAL_ERR_INTERNAL;
    }
    return render->control.Flush((AudioHandle)render);
}

int32_t HdiServiceRenderGetFrameSize(const struct HdfDeviceIoClient *client,
    struct HdfSBuf *data, struct HdfSBuf *reply)
{
    if (client == NULL || data == NULL || reply == NULL) {
        return AUDIO_HAL_ERR_INVALID_PARAM;
    }
    uint64_t size;
    struct AudioRender *render = NULL;
    int ret = AudioAdapterListCheckAndGetRender(&render, data);
    if (ret < 0) {
        return ret;
    }
    if (render == NULL || render->attr.GetFrameSize == NULL) {
        AUDIO_FUNC_LOGE("render or GetFrameSize is NULL");
        return AUDIO_HAL_ERR_INTERNAL;
    }
    if (render->attr.GetFrameSize((AudioHandle)render, &size)) {
        return AUDIO_HAL_ERR_INTERNAL;
    }
    if (!HdfSbufWriteUint64(reply, size)) {
        return AUDIO_HAL_ERR_INTERNAL;
    }
    return AUDIO_HAL_SUCCESS;
}

int32_t HdiServiceRenderGetFrameCount(const struct HdfDeviceIoClient *client,
    struct HdfSBuf *data, struct HdfSBuf *reply)
{
    if (client == NULL || data == NULL || reply == NULL) {
        AUDIO_FUNC_LOGE("client or data or reply is NULL!");
        return AUDIO_HAL_ERR_INVALID_PARAM;
    }
    uint64_t count;
    struct AudioRender *render = NULL;
    int ret = AudioAdapterListCheckAndGetRender(&render, data);
    if (ret < 0) {
        return ret;
    }
    if (render == NULL || render->attr.GetFrameCount == NULL) {
        AUDIO_FUNC_LOGE("render or GetFrameCount is NULL");
        return AUDIO_HAL_ERR_INTERNAL;
    }
    if (render->attr.GetFrameCount((AudioHandle)render, &count)) {
        return AUDIO_HAL_ERR_INTERNAL;
    }
    if (!HdfSbufWriteUint64(reply, count)) {
        return AUDIO_HAL_ERR_INTERNAL;
    }
    return AUDIO_HAL_SUCCESS;
}

int32_t HdiServiceRenderSetSampleAttr(const struct HdfDeviceIoClient *client,
    struct HdfSBuf *data, struct HdfSBuf *reply)
{
    if (client == NULL || data == NULL || reply == NULL) {
        return AUDIO_HAL_ERR_INVALID_PARAM;
    }
    int ret;
    struct AudioSampleAttributes attrs;
    struct AudioRender *render = NULL;
    ret = AudioAdapterListCheckAndGetRender(&render, data);
    if (ret < 0) {
        return ret;
    }
    if (ReadAudioSapmleAttrbutes(data, &attrs) < 0) {
        return AUDIO_HAL_ERR_INTERNAL;
    }
    if (render == NULL || render->attr.SetSampleAttributes == NULL) {
        AUDIO_FUNC_LOGE("render or SetSampleAttributes is NULL");
        return AUDIO_HAL_ERR_INTERNAL;
    }
    return render->attr.SetSampleAttributes((AudioHandle)render, &attrs);
}

int32_t HdiServiceRenderGetSampleAttr(const struct HdfDeviceIoClient *client,
    struct HdfSBuf *data, struct HdfSBuf *reply)
{
    if (client == NULL || data == NULL || reply == NULL) {
        return AUDIO_HAL_ERR_INVALID_PARAM;
    }
    struct AudioSampleAttributes attrs;
    struct AudioRender *render = NULL;
    int32_t ret = AudioAdapterListCheckAndGetRender(&render, data);
    if (ret < 0) {
        return ret;
    }
    if (render == NULL || render->attr.GetSampleAttributes == NULL) {
        AUDIO_FUNC_LOGE("render or GetSampleAttributes is NULL");
        return AUDIO_HAL_ERR_INTERNAL;
    }
    ret = render->attr.GetSampleAttributes((AudioHandle)render, &attrs);
    if (ret < 0) {
        return ret;
    }
    if (WriteAudioSampleAttributes(reply, &attrs) < 0) {
        return AUDIO_HAL_ERR_INTERNAL;
    }
    return AUDIO_HAL_SUCCESS;
}

int32_t HdiServiceRenderGetCurChannelId(const struct HdfDeviceIoClient *client,
    struct HdfSBuf *data, struct HdfSBuf *reply)
{
    if (client == NULL || data == NULL || reply == NULL) {
        return AUDIO_HAL_ERR_INVALID_PARAM;
    }
    uint32_t channelId;
    struct AudioRender *render = NULL;
    int ret = AudioAdapterListCheckAndGetRender(&render, data);
    if (ret < 0) {
        return ret;
    }
    if (render == NULL || render->attr.GetCurrentChannelId == NULL) {
        AUDIO_FUNC_LOGE("render or GetCurrentChannelId is NULL");
        return AUDIO_HAL_ERR_INTERNAL;
    }
    ret = render->attr.GetCurrentChannelId((AudioHandle)render, &channelId);
    if (ret < 0) {
        return ret;
    }
    if (!HdfSbufWriteUint32(reply, channelId)) {
        return AUDIO_HAL_ERR_INTERNAL;
    }
    return AUDIO_HAL_SUCCESS;
}

int32_t HdiServiceRenderCheckSceneCapability(const struct HdfDeviceIoClient *client,
    struct HdfSBuf *data, struct HdfSBuf *reply)
{
    if (client == NULL || data == NULL || reply == NULL) {
        return AUDIO_HAL_ERR_INVALID_PARAM;
    }
    uint32_t temporaryPins = 0;
    struct AudioSceneDescriptor scene;
    bool supported = false;
    struct AudioRender *render = NULL;
    int ret = AudioAdapterListCheckAndGetRender(&render, data);
    if (ret < 0) {
        return ret;
    }
    if (!HdfSbufReadUint32(data, &scene.scene.id)) {
        return AUDIO_HAL_ERR_INTERNAL;
    }
    if (!HdfSbufReadUint32(data, &temporaryPins)) {
        return AUDIO_HAL_ERR_INTERNAL;
    }
    scene.desc.pins = (enum AudioPortPin)temporaryPins;
    if (render == NULL || render->scene.CheckSceneCapability == NULL) {
        AUDIO_FUNC_LOGE("render or CheckSceneCapability is NULL");
        return AUDIO_HAL_ERR_INTERNAL;
    }
    ret = render->scene.CheckSceneCapability((AudioHandle)render, &scene, &supported);
    if (ret < 0) {
        return ret;
    }
    uint32_t tempSupported = (uint32_t)supported;
    if (!HdfSbufWriteUint32(reply, tempSupported)) {
        return AUDIO_HAL_ERR_INTERNAL;
    }
    return AUDIO_HAL_SUCCESS;
}

int32_t HdiServiceRenderSelectScene(const struct HdfDeviceIoClient *client,
    struct HdfSBuf *data, struct HdfSBuf *reply)
{
    if (client == NULL || data == NULL || reply == NULL) {
        return AUDIO_HAL_ERR_INVALID_PARAM;
    }
    uint32_t tempPins = 0;
    struct AudioSceneDescriptor scene;
    struct AudioRender *render = NULL;
    int ret = AudioAdapterListCheckAndGetRender(&render, data);
    if (ret < 0) {
        return ret;
    }
    if (!HdfSbufReadUint32(data, &scene.scene.id)) {
        AUDIO_FUNC_LOGI("Read id Fail");
        return AUDIO_HAL_ERR_INTERNAL;
    }
    if (!HdfSbufReadUint32(data, &tempPins)) {
        AUDIO_FUNC_LOGI("Read tempPins Fail");
        return AUDIO_HAL_ERR_INTERNAL;
    }
    scene.desc.pins = (enum AudioPortPin)tempPins;
    if (render == NULL || render->scene.SelectScene == NULL) {
        AUDIO_FUNC_LOGE("render or SelectScene is NULL");
        return AUDIO_HAL_ERR_INTERNAL;
    }
    return render->scene.SelectScene((AudioHandle)render, &scene);
}

int32_t HdiServiceRenderGetMute(const struct HdfDeviceIoClient *client,
    struct HdfSBuf *data, struct HdfSBuf *reply)
{
    if (client == NULL || data == NULL || reply == NULL) {
        AUDIO_FUNC_LOGI("parameter is empty");
        return AUDIO_HAL_ERR_INVALID_PARAM;
    }
    bool mute = false;
    struct AudioRender *render = NULL;
    int ret = AudioAdapterListCheckAndGetRender(&render, data);
    if (ret < 0) {
        return ret;
    }
    if (render == NULL || render->volume.GetMute == NULL) {
        AUDIO_FUNC_LOGE("render or GetMute is NULL");
        return AUDIO_HAL_ERR_INTERNAL;
    }
    ret = render->volume.GetMute((AudioHandle)render, &mute);
    if (ret < 0) {
        return ret;
    }
    uint32_t tempMute = (uint32_t)mute;
    if (!HdfSbufWriteUint32(reply, tempMute)) {
        return AUDIO_HAL_ERR_INTERNAL;
    }
    return AUDIO_HAL_SUCCESS;
}

int32_t HdiServiceRenderSetMute(const struct HdfDeviceIoClient *client,
    struct HdfSBuf *data, struct HdfSBuf *reply)
{
    if (client == NULL || data == NULL || reply == NULL) {
        return AUDIO_HAL_ERR_INVALID_PARAM;
    }
    bool mute = false;
    struct AudioRender *render = NULL;
    int ret = AudioAdapterListCheckAndGetRender(&render, data);
    if (ret < 0) {
        return ret;
    }
    uint32_t tempMute = 0;
    if (!HdfSbufReadUint32(data, &tempMute)) {
        return AUDIO_HAL_ERR_INTERNAL;
    }
    mute = (bool)tempMute;
    if (render == NULL || render->volume.SetMute == NULL) {
        AUDIO_FUNC_LOGE("render or SetMute is NULL");
        return AUDIO_HAL_ERR_INTERNAL;
    }
    return render->volume.SetMute((AudioHandle)render, mute);
}

int32_t HdiServiceRenderSetVolume(const struct HdfDeviceIoClient *client,
    struct HdfSBuf *data, struct HdfSBuf *reply)
{
    if (client == NULL || data == NULL || reply == NULL) {
        return AUDIO_HAL_ERR_INVALID_PARAM;
    }
    uint32_t volume = 0;
    struct AudioRender *render = NULL;
    int ret = AudioAdapterListCheckAndGetRender(&render, data);
    if (ret < 0) {
        return ret;
    }
    if (!HdfSbufReadUint32(data, &volume)) {
        return AUDIO_HAL_ERR_INTERNAL;
    }
    float setVolume = (float)volume / VOLUME_CHANGE;
    if (render == NULL || render->volume.SetVolume == NULL) {
        AUDIO_FUNC_LOGE("render or SetVolume is NULL");
        return AUDIO_HAL_ERR_INTERNAL;
    }
    return render->volume.SetVolume((AudioHandle)render, setVolume);
}

int32_t HdiServiceRenderGetVolume(const struct HdfDeviceIoClient *client,
    struct HdfSBuf *data, struct HdfSBuf *reply)
{
    if (client == NULL || data == NULL || reply == NULL) {
        return AUDIO_HAL_ERR_INVALID_PARAM;
    }
    float volume;
    struct AudioRender *render = NULL;
    int ret = AudioAdapterListCheckAndGetRender(&render, data);
    if (ret < 0) {
        return ret;
    }
    if (render == NULL || render->volume.GetVolume == NULL) {
        AUDIO_FUNC_LOGE("render or GetVolume is NULL");
        return AUDIO_HAL_ERR_INTERNAL;
    }
    ret = render->volume.GetVolume((AudioHandle)render, &volume);
    if (ret < 0) {
        return ret;
    }
    uint32_t tempVolume = (uint32_t)(volume * VOLUME_CHANGE);
    if (!HdfSbufWriteUint32(reply, tempVolume)) {
        return AUDIO_HAL_ERR_INTERNAL;
    }
    return AUDIO_HAL_SUCCESS;
}

int32_t HdiServiceRenderGetGainThreshold(const struct HdfDeviceIoClient *client,
    struct HdfSBuf *data, struct HdfSBuf *reply)
{
    if (client == NULL || data == NULL || reply == NULL) {
        return AUDIO_HAL_ERR_INVALID_PARAM;
    }
    float min, max;
    struct AudioRender *render = NULL;
    int ret = AudioAdapterListCheckAndGetRender(&render, data);
    if (ret < 0) {
        return ret;
    }
    if (render == NULL || render->volume.GetGainThreshold == NULL) {
        AUDIO_FUNC_LOGE("render or GetGainThreshold is NULL");
        return AUDIO_HAL_ERR_INTERNAL;
    }
    ret = render->volume.GetGainThreshold((AudioHandle)render, &min, &max);
    if (ret < 0) {
        return ret;
    }
    uint32_t temporaryMin = (uint32_t)min;
    if (!HdfSbufWriteUint32(reply, temporaryMin)) {
        return AUDIO_HAL_ERR_INTERNAL;
    }
    uint32_t temporaryMax = (uint32_t)max;
    if (!HdfSbufWriteUint32(reply, temporaryMax)) {
        return AUDIO_HAL_ERR_INTERNAL;
    }
    return AUDIO_HAL_SUCCESS;
}

int32_t HdiServiceRenderGetGain(const struct HdfDeviceIoClient *client,
    struct HdfSBuf *data, struct HdfSBuf *reply)
{
    if (client == NULL || data == NULL || reply == NULL) {
        return AUDIO_HAL_ERR_INVALID_PARAM;
    }
    float gain;
    struct AudioRender *render = NULL;
    int ret = AudioAdapterListCheckAndGetRender(&render, data);
    if (ret < 0) {
        return ret;
    }
    if (render == NULL || render->volume.GetGain == NULL) {
        AUDIO_FUNC_LOGE("render or GetGain is NULL");
        return AUDIO_HAL_ERR_INTERNAL;
    }
    ret = render->volume.GetGain((AudioHandle)render, &gain);
    if (ret < 0) {
        return ret;
    }
    uint32_t tempGain = (uint32_t)gain;
    if (!HdfSbufWriteUint32(reply, tempGain)) {
        return AUDIO_HAL_ERR_INTERNAL;
    }
    return AUDIO_HAL_SUCCESS;
}

int32_t HdiServiceRenderSetGain(const struct HdfDeviceIoClient *client,
    struct HdfSBuf *data, struct HdfSBuf *reply)
{
    if (client == NULL || data == NULL || reply == NULL) {
        return AUDIO_HAL_ERR_INVALID_PARAM;
    }
    uint32_t tempGain = 0;
    struct AudioRender *render = NULL;
    int ret = AudioAdapterListCheckAndGetRender(&render, data);
    if (ret < 0) {
        return ret;
    }
    if (!HdfSbufReadUint32(data, &tempGain)) {
        return AUDIO_HAL_ERR_INTERNAL;
    }
    if (render == NULL || render->volume.SetGain == NULL) {
        AUDIO_FUNC_LOGE("render or SetGain is NULL");
        return AUDIO_HAL_ERR_INTERNAL;
    }
    return render->volume.SetGain((AudioHandle)render, (float)tempGain);
}

int32_t HdiServiceRenderGetLatency(const struct HdfDeviceIoClient *client,
    struct HdfSBuf *data, struct HdfSBuf *reply)
{
    if (client == NULL || data == NULL || reply == NULL) {
        return AUDIO_HAL_ERR_INVALID_PARAM;
    }
    uint32_t ms;
    struct AudioRender *render = NULL;
    int ret = AudioAdapterListCheckAndGetRender(&render, data);
    if (ret < 0) {
        return ret;
    }
    if (render == NULL || render->GetLatency == NULL) {
        AUDIO_FUNC_LOGE("render or GetLatency is NULL");
        return AUDIO_HAL_ERR_INTERNAL;
    }
    ret = render->GetLatency((AudioHandle)render, &ms);
    if (ret < 0) {
        return ret;
    }
    if (!HdfSbufWriteUint32(reply, ms)) {
        return AUDIO_HAL_ERR_INTERNAL;
    }
    return AUDIO_HAL_SUCCESS;
}

int32_t HdiServiceRenderRenderFrame(const struct HdfDeviceIoClient *client,
    struct HdfSBuf *data, struct HdfSBuf *reply)
{
    if (client == NULL || data == NULL || reply == NULL) {
        return AUDIO_HAL_ERR_INVALID_PARAM;
    }
    char *frame = NULL;
    uint32_t requestBytes = 0;
    uint64_t replyBytes = 0;
    struct AudioRender *render = NULL;
    const char *adapterName = NULL;
    uint32_t pid = 0;
    if (HdiServiceRenderCaptureReadData(data, &adapterName, &pid) < 0) {
        AUDIO_FUNC_LOGE("HdiServiceRenderCaptureReadData fail!");
        return AUDIO_HAL_ERR_INTERNAL;
    }
    int32_t ret = AudioAdapterListGetRender(adapterName, &render, pid);
    if (ret < 0) {
        AUDIO_FUNC_LOGE("AudioAdapterListGetRender fail");
        return ret;
    }
    ret = AudioGetRenderStatus(adapterName);
    if (ret < 0) {
        AUDIO_FUNC_LOGE("AudioGetRenderStatus fail");
        return ret;
    }
    if (!HdfSbufReadBuffer(data, (const void **)&frame, &requestBytes)) {
        AUDIO_FUNC_LOGE("AudioAdapterListGetRender:HdfSbufReadBuffer fail");
        return AUDIO_HAL_ERR_INTERNAL;
    }
    AudioSetRenderStatus(adapterName, true);
    (void)OsalMutexLock(&g_renderLock);
    if (render == NULL || render->RenderFrame == NULL) {
        AUDIO_FUNC_LOGE("render or RenderFrame is NULL");
        return AUDIO_HAL_ERR_INTERNAL;
    }
    ret = render->RenderFrame((AudioHandle)render, (const void *)frame, (uint64_t)requestBytes, &replyBytes);
    (void)OsalMutexUnlock(&g_renderLock);
    AudioSetRenderStatus(adapterName, false);
    if (ret < 0) {
        AUDIO_FUNC_LOGE("HdiServiceRenderRenderFrame fail");
        return ret;
    }
    return AUDIO_HAL_SUCCESS;
}

int32_t HdiServiceRenderGetRenderPosition(const struct HdfDeviceIoClient *client,
    struct HdfSBuf *data, struct HdfSBuf *reply)
{
    if (client == NULL || data == NULL || reply == NULL) {
        return AUDIO_HAL_ERR_INVALID_PARAM;
    }
    struct AudioTimeStamp time;
    struct AudioRender *render = NULL;
    uint64_t frames;
    int ret = AudioAdapterListCheckAndGetRender(&render, data);
    if (ret < 0) {
        return ret;
    }
    (void)OsalMutexLock(&g_renderLock);
    if (render == NULL || render->GetRenderPosition == NULL) {
        AUDIO_FUNC_LOGE("render or GetRenderPosition is NULL");
        return AUDIO_HAL_ERR_INTERNAL;
    }
    ret = render->GetRenderPosition((AudioHandle)render, &frames, &time);
    (void)OsalMutexUnlock(&g_renderLock);
    if (ret < 0) {
        return ret;
    }
    ret = HdiServicePositionWrite(reply, frames, time);
    if (ret < 0) {
        return AUDIO_HAL_ERR_INTERNAL;
    }
    return AUDIO_HAL_SUCCESS;
}

int32_t HdiServiceRenderGetSpeed(const struct HdfDeviceIoClient *client,
    struct HdfSBuf *data, struct HdfSBuf *reply)
{
    if (client == NULL || data == NULL || reply == NULL) {
        return AUDIO_HAL_ERR_INVALID_PARAM;
    }
    float speed;
    struct AudioRender *render = NULL;
    int ret = AudioAdapterListCheckAndGetRender(&render, data);
    if (ret < 0) {
        return ret;
    }
    if (render == NULL || render->GetRenderSpeed == NULL) {
        AUDIO_FUNC_LOGE("render or GetRenderSpeed is NULL");
        return AUDIO_HAL_ERR_INTERNAL;
    }
    ret = render->GetRenderSpeed((AudioHandle)render, &speed);
    if (ret < 0) {
        return ret;
    }
    uint64_t tempSpeed = (uint64_t)speed;
    if (!HdfSbufWriteUint64(reply, tempSpeed)) {
        return AUDIO_HAL_ERR_INTERNAL;
    }
    return AUDIO_HAL_SUCCESS;
}

int32_t HdiServiceRenderSetSpeed(const struct HdfDeviceIoClient *client,
    struct HdfSBuf *data, struct HdfSBuf *reply)
{
    if (client == NULL || data == NULL || reply == NULL) {
        return AUDIO_HAL_ERR_INVALID_PARAM;
    }
    uint64_t speed = 0;
    struct AudioRender *render = NULL;
    int ret = AudioAdapterListCheckAndGetRender(&render, data);
    if (ret < 0) {
        return ret;
    }
    if (!HdfSbufReadUint64(data, &speed)) {
        return AUDIO_HAL_ERR_INTERNAL;
    }
    if (render == NULL || render->SetRenderSpeed == NULL) {
        AUDIO_FUNC_LOGE("render or SetRenderSpeed is NULL");
        return AUDIO_HAL_ERR_INTERNAL;
    }
    return render->SetRenderSpeed((AudioHandle)render, (float)speed);
}

int32_t HdiServiceRenderSetChannelMode(const struct HdfDeviceIoClient *client,
    struct HdfSBuf *data, struct HdfSBuf *reply)
{
    if (client == NULL || data == NULL || reply == NULL) {
        return AUDIO_HAL_ERR_INVALID_PARAM;
    }
    enum AudioChannelMode mode;
    struct AudioRender *render = NULL;
    int ret = AudioAdapterListCheckAndGetRender(&render, data);
    if (ret < 0) {
        AUDIO_FUNC_LOGE("AudioAdapterListCheckAndGetRender failed.");
        return ret;
    }
    uint32_t tempMode = 0;
    if (!HdfSbufReadUint32(data, &tempMode)) {
        return AUDIO_HAL_ERR_INTERNAL;
    }
    mode = (enum AudioChannelMode)tempMode;
    if (render == NULL || render->SetChannelMode == NULL) {
        AUDIO_FUNC_LOGE("render or SetChannelMode is NULL");
        return AUDIO_HAL_ERR_INTERNAL;
    }
    return render->SetChannelMode((AudioHandle)render, mode);
}

int32_t HdiServiceRenderGetChannelMode(const struct HdfDeviceIoClient *client,
    struct HdfSBuf *data, struct HdfSBuf *reply)
{
    if (client == NULL || data == NULL || reply == NULL) {
        return AUDIO_HAL_ERR_INVALID_PARAM;
    }
    enum AudioChannelMode mode;
    struct AudioRender *render = NULL;
    int ret = AudioAdapterListCheckAndGetRender(&render, data);
    if (ret < 0) {
        AUDIO_FUNC_LOGE("CheckAndGetRender failed.");
        return ret;
    }
    if (render == NULL || render->GetChannelMode == NULL) {
        AUDIO_FUNC_LOGE("render or GetChannelMode is NULL");
        return AUDIO_HAL_ERR_INTERNAL;
    }
    ret = render->GetChannelMode((AudioHandle)render, &mode);
    if (ret < 0) {
        return ret;
    }
    uint32_t tempMode = (uint32_t)mode;
    if (!HdfSbufWriteUint32(reply, tempMode)) {
        return AUDIO_HAL_ERR_INTERNAL;
    }
    return AUDIO_HAL_SUCCESS;
}

int32_t HdiServiceRenderSetExtraParams(const struct HdfDeviceIoClient *client,
    struct HdfSBuf *data, struct HdfSBuf *reply)
{
    if (client == NULL || data == NULL || reply == NULL) {
        return AUDIO_HAL_ERR_INVALID_PARAM;
    }
    struct AudioRender *render = NULL;
    int32_t ret = AudioAdapterListCheckAndGetRender(&render, data);
    if (ret < 0) {
        return ret;
    }
    const char *keyValueList = NULL;
    if ((keyValueList = HdfSbufReadString(data)) == NULL) {
        AUDIO_FUNC_LOGE("keyValueList Is NULL");
        return AUDIO_HAL_ERR_INTERNAL;
    }
    if (render == NULL || render->attr.SetExtraParams == NULL) {
        AUDIO_FUNC_LOGE("render or SetExtraParams is NULL");
        return AUDIO_HAL_ERR_INTERNAL;
    }
    return render->attr.SetExtraParams((AudioHandle)render, keyValueList);
}

int32_t HdiServiceRenderGetExtraParams(const struct HdfDeviceIoClient *client,
    struct HdfSBuf *data, struct HdfSBuf *reply)
{
    if (client == NULL || data == NULL || reply == NULL) {
        return AUDIO_HAL_ERR_INVALID_PARAM;
    }
    int32_t listLenth = 0;
    struct AudioRender *render = NULL;
    int ret = AudioAdapterListCheckAndGetRender(&render, data);
    if (ret < 0) {
        return ret;
    }
    if (!HdfSbufReadInt32(data, &listLenth)) {
        return AUDIO_HAL_ERR_INTERNAL;
    }
    if (listLenth <= 0 || listLenth > STR_MAX - 1) {
        return AUDIO_HAL_ERR_INTERNAL;
    }
    char keyValueList[STR_MAX] = { 0 };
    if (render == NULL || render->attr.GetExtraParams == NULL) {
        AUDIO_FUNC_LOGE("render or GetExtraParams is NULL");
        return AUDIO_HAL_ERR_INTERNAL;
    }
    ret = render->attr.GetExtraParams((AudioHandle)render, keyValueList, listLenth);
    if (ret < 0) {
        return ret;
    }
    if (!HdfSbufWriteString(reply, keyValueList)) {
        return AUDIO_HAL_ERR_INTERNAL;
    }
    return AUDIO_HAL_SUCCESS;
}

int32_t HdiServiceRenderReqMmapBuffer(const struct HdfDeviceIoClient *client,
    struct HdfSBuf *data, struct HdfSBuf *reply)
{
    if (client == NULL || data == NULL || reply == NULL) {
        return AUDIO_HAL_ERR_INVALID_PARAM;
    }
    struct AudioMmapBufferDescriptor desc;
    int32_t reqSize = 0;
    struct AudioRender *render = NULL;
    int ret = AudioAdapterListCheckAndGetRender(&render, data);
    if (ret < 0) {
        return ret;
    }
    if (!HdfSbufReadInt32(data, &reqSize)) {
        return AUDIO_HAL_ERR_INTERNAL;
    }
    if (HdiServiceReqMmapBuffer(&desc, data) < 0) {
        return AUDIO_HAL_ERR_INTERNAL;
    }
    if (render == NULL || render->attr.ReqMmapBuffer == NULL) {
        AUDIO_FUNC_LOGE("render or ReqMmapBuffer is NULL");
        return AUDIO_HAL_ERR_INTERNAL;
    }
    ret = render->attr.ReqMmapBuffer((AudioHandle)render, reqSize, &desc);
    if (ret < 0) {
        AUDIO_FUNC_LOGE("ReqMmapBuffer fail");
        return ret;
    }

    if (!HdfSbufWriteFileDescriptor(reply, desc.memoryFd)) {
        AUDIO_FUNC_LOGE("memoryFd write fail");
        return AUDIO_HAL_ERR_INTERNAL;
    }

    if (!HdfSbufWriteInt32(reply, desc.totalBufferFrames)) {
        AUDIO_FUNC_LOGE("totalBufferFrames write fail");
        return AUDIO_HAL_ERR_INTERNAL;
    }

    if (!HdfSbufWriteInt32(reply, desc.transferFrameSize)) {
        AUDIO_FUNC_LOGE("transferFrameSize write fail");
        return AUDIO_HAL_ERR_INTERNAL;
    }

    if (!HdfSbufWriteInt32(reply, desc.isShareable)) {
        AUDIO_FUNC_LOGE("isShareable write fail");
        return AUDIO_HAL_ERR_INTERNAL;
    }

    if (!HdfSbufWriteUint32(reply, desc.offset)) {
        AUDIO_FUNC_LOGE("offset write fail");
        return AUDIO_HAL_ERR_INTERNAL;
    }
    return AUDIO_HAL_SUCCESS;
}

int32_t HdiServiceRenderGetMmapPosition(const struct HdfDeviceIoClient *client,
    struct HdfSBuf *data, struct HdfSBuf *reply)
{
    AUDIO_FUNC_LOGD("enter");
    if (client == NULL || data == NULL || reply == NULL) {
        return AUDIO_HAL_ERR_INVALID_PARAM;
    }
    uint64_t frames;
    struct AudioTimeStamp time;
    struct AudioRender *render = NULL;
    int ret = AudioAdapterListCheckAndGetRender(&render, data);
    if (ret < 0) {
        return ret;
    }
    if (render == NULL || render->attr.GetMmapPosition == NULL) {
        AUDIO_FUNC_LOGE("render or GetMmapPosition is NULL");
        return AUDIO_HAL_ERR_INTERNAL;
    }
    ret = render->attr.GetMmapPosition((AudioHandle)render, &frames, &time);
    if (ret < 0) {
        return ret;
    }
    if (HdiServicePositionWrite(reply, frames, time) < 0) {
        return AUDIO_HAL_ERR_INTERNAL;
    }
    AUDIO_FUNC_LOGD("out");
    return AUDIO_HAL_SUCCESS;
}

int32_t HdiServiceRenderAddEffect(const struct HdfDeviceIoClient *client,
    struct HdfSBuf *data, struct HdfSBuf *reply)
{
    (void)client;
    (void)reply;
    uint64_t effectid = 0;
    struct AudioRender *render = NULL;
    if (data == NULL) {
        return AUDIO_HAL_ERR_INVALID_PARAM;
    }

    int32_t ret = AudioAdapterListCheckAndGetRender(&render, data);
    if (ret < 0 || render == NULL) {
        AUDIO_FUNC_LOGE("render is null or ret = %{public}d", ret);
        return ret;
    }

    if (!HdfSbufReadUint64(data, &effectid)) {
        AUDIO_FUNC_LOGE("HdfSbufReadUint64 failed.");
        return HDF_FAILURE;
    }

    if (render->attr.AddAudioEffect == NULL) {
        AUDIO_FUNC_LOGE("AddAudioEffect is NULL");
        return AUDIO_HAL_ERR_INTERNAL;
    }
    return render->attr.AddAudioEffect((AudioHandle)render, effectid);
}

int32_t HdiServiceRenderRemoveEffect(const struct HdfDeviceIoClient *client,
    struct HdfSBuf *data, struct HdfSBuf *reply)
{
    (void)client;
    (void)reply;
    uint64_t effectid = 0;
    if (data == NULL) {
        return AUDIO_HAL_ERR_INVALID_PARAM;
    }

    struct AudioRender *render = NULL;
    int32_t ret = AudioAdapterListCheckAndGetRender(&render, data);
    if (ret < 0 || render == NULL) {
        AUDIO_FUNC_LOGE("render is NULL or ret = %{public}d", ret);
        return ret;
    }

    if (!HdfSbufReadUint64(data, &effectid)) {
        AUDIO_FUNC_LOGE("read buf fail ");
        return HDF_FAILURE;
    }

    if (render->attr.RemoveAudioEffect == NULL) {
        AUDIO_FUNC_LOGE("RemoveAudioEffect is NULL");
        return AUDIO_HAL_ERR_INTERNAL;
    }
    return render->attr.RemoveAudioEffect((AudioHandle)render, effectid);
}

int32_t HdiServiceRenderTurnStandbyMode(const struct HdfDeviceIoClient *client,
    struct HdfSBuf *data, struct HdfSBuf *reply)
{
    if (client == NULL || data == NULL || reply == NULL) {
        AUDIO_FUNC_LOGE("The pointer is null");
        return AUDIO_HAL_ERR_INVALID_PARAM;
    }
    struct AudioRender *render = NULL;
    int ret = AudioAdapterListCheckAndGetRender(&render, data);
    if (ret < 0) {
        return ret;
    }
    if (render == NULL || render->control.Stop == NULL) {
        AUDIO_FUNC_LOGE("render or Stop is NULL");
        return AUDIO_HAL_ERR_INTERNAL;
    }
    return render->control.Stop((AudioHandle)render);
}

int32_t HdiServiceRenderDevDump(const struct HdfDeviceIoClient *client,
    struct HdfSBuf *data, struct HdfSBuf *reply)
{
    if (client == NULL || data == NULL || reply == NULL) {
        return AUDIO_HAL_ERR_INVALID_PARAM;
    }
    int32_t range = 0;
    struct AudioRender *render = NULL;
    int ret = AudioAdapterListCheckAndGetRender(&render, data);
    if (ret < 0) {
        return ret;
    }
    if (!HdfSbufReadInt32(data, &range)) {
        return AUDIO_HAL_ERR_INTERNAL;
    }
    ret = HdfSbufReadFileDescriptor(data);
    if (ret < 0) {
        return AUDIO_HAL_ERR_INTERNAL;
    }
    int32_t fd = ret;
    if (render == NULL || render->control.AudioDevDump == NULL) {
        AUDIO_FUNC_LOGE("render or AudioDevDump is NULL");
        return AUDIO_HAL_ERR_INTERNAL;
    }
    return render->control.AudioDevDump((AudioHandle)render, range, fd);
}

int32_t HdiServiceRenderRegCallback(const struct HdfDeviceIoClient *client, struct HdfSBuf *data, struct HdfSBuf *reply)
{
    if (client == NULL || data == NULL || reply == NULL) {
        return AUDIO_HAL_ERR_INVALID_PARAM;
    }
    struct AudioRender *render = NULL;
    int ret = AudioAdapterListCheckAndGetRender(&render, data);
    if (ret < 0) {
        return ret;
    }
    void *cookie;
    RenderCallback pCallback;
    uint64_t tempAddr = 0;
    if (!HdfSbufReadUint64(data, &tempAddr)) {
        AUDIO_FUNC_LOGE("read cookie Is NULL");
        return AUDIO_HAL_ERR_INTERNAL;
    }
    cookie = (void *)(uintptr_t)tempAddr;
    if (!HdfSbufReadUint64(data, &tempAddr)) {
        AUDIO_FUNC_LOGE("read callback pointer Is NULL");
        return AUDIO_HAL_ERR_INTERNAL;
    }
    pCallback = (RenderCallback)(uintptr_t)tempAddr;
    if (render == NULL || render->RegCallback == NULL) {
        AUDIO_FUNC_LOGE("render or RegCallback is NULL");
        return AUDIO_HAL_ERR_INTERNAL;
    }
    return render->RegCallback((AudioHandle)render, pCallback, cookie);
}

int32_t HdiServiceRenderDrainBuffer(const struct HdfDeviceIoClient *client, struct HdfSBuf *data, struct HdfSBuf *reply)
{
    if (client == NULL || data == NULL || reply == NULL) {
        return AUDIO_HAL_ERR_INVALID_PARAM;
    }
    struct AudioRender *render = NULL;
    int ret = AudioAdapterListCheckAndGetRender(&render, data);
    if (ret < 0) {
        return ret;
    }
    enum AudioDrainNotifyType type;
    uint32_t tempType = 0;
    if (!HdfSbufReadUint32(data, &tempType)) {
        return AUDIO_HAL_ERR_INTERNAL;
    }
    type = (enum AudioDrainNotifyType)tempType;
    if (render == NULL || render->DrainBuffer == NULL) {
        AUDIO_FUNC_LOGE("render or DrainBuffer is NULL");
        return AUDIO_HAL_ERR_INTERNAL;
    }
    return render->DrainBuffer((AudioHandle)render, &type);
}

